#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>


#define LEFT "["
#define RIGHT "]"
#define LABLE "#"
#define LINE_SIZE 1024
#define ARGC_SIZE 32
#define DELIM " \t"
#define EXIT_CODE 1


int lastCode = 0;
int quit = 0;
char commandLine[LINE_SIZE];
char* argv[ARGC_SIZE];
char pwd[LINE_SIZE];
char myenv[LINE_SIZE];

const char* GetUserName()
{
   return getenv("USER");
}

const char* GetHostname()
{
    return getenv("HOSTNAME");
}
void GetPWD()
{
    getcwd(pwd, sizeof(pwd));
}

void Interact(char* cline, int size)
{
    GetPWD();
    printf(LEFT"%s@%s %s"RIGHT""LABLE" ", GetUserName(), GetHostname(), pwd);
    char* input = fgets(cline, size, stdin);
    assert(input);
    (void)input;

    cline[strlen(cline) - 1] = '\0';

}

int SplitString(char* cline, char* _argv[])
{
    int i = 0;
    _argv[i++] = strtok(cline, DELIM);
    while(_argv[i++] = strtok(NULL, DELIM));
    
    return i - 1;
}

void NormalExcute(char* _argv[])
{
    pid_t id = fork();
    if(id < 0)
    {
        perror("fork");
        return;
    }
    else if(id == 0)
    {
        execvp(_argv[0], argv);
        exit(EXIT_CODE);
    }
    else 
    {
        int status = 0;
        pid_t ret = waitpid(id, &status, 0);
        if(ret == id) lastCode = WEXITSTATUS(status);
    }
}

int BuildExcute(char* _argv[], int _argc)
{
    if(_argc == 2 && strcmp(_argv[0], "cd") == 0)
    {
        chdir(_argv[1]);
        GetPWD();
        sprintf(getenv("PWD"), "%s", pwd);
        return 1;
    }
    else if(_argc == 2 && strcmp(_argv[0], "export") == 0)
    {
        strcpy(myenv, _argv[1]);
        putenv(myenv);
        return 1;
    }
    else if(_argc == 2 && strcmp(_argv[0], "echo") == 0)
    {
        if(strcmp(_argv[1], "$?") == 0)
        {
            printf("%d\n", lastCode);
            lastCode = 0;
        }
        else if(*_argv[1] == '$')
        {
            char* val = getenv(_argv[1]+1);
            if(val) printf("%s\n", val);
        }
        else 
        {
            printf("%s\n", _argv[1]);
        }
        
        return 1;
    }

    if(strcmp(_argv[0], "ls") == 0)
    {
        _argv[_argc++] = "--color";
        _argv[_argc] = NULL;
    }

    return 0;
}



int main()
{
    
    while(!quit)
    {
        // 1. 交互
        Interact(commandLine, sizeof(commandLine));
        
        // 2. 解析命令
        int argc = SplitString(commandLine, argv);
        if(argc == 0) continue;
        
        //for(int i = 0; argv[i]; ++i) printf("%d: %s\n", i, argv[i]);
    
        // 3. 指令判断
        int n =  BuildExcute(argv, argc);

        if(!n) NormalExcute(argv);
    }
    
    return 0;    
}
